using System;
using System.Data;
using Headspring.Training.Core.Model;
using NHibernate;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;

namespace Headspring.Training.IntegrationTests
{
	[TestFixture]
	public class PopQuizTester : DataTestBase
	{
		[Test]
		public void Question1()
		{
			var employee = new Employee("1", "1", "1", "1");
			var order = new WorkOrder
			            	{
			            		Creator = employee,
			            		Assignee = employee,
			            		CreatedDate = new DateTime(1999, 1, 1),
			            		CompletedDate = new DateTime(1999, 1, 2),
			            		Title = "foo",
			            		Description = "oldvalue",
			            		Status = WorkOrderStatus.InProgress,
			            		Number = "123"
			            	};

			ISession session = getSession();
			session.SaveOrUpdate(employee);
			session.SaveOrUpdate(order);
			session.Flush();

			employee.FirstName = "newvalue";
			order.Title = "newvalue";

			IDbCommand command = session.Connection.CreateCommand();
			command.CommandText =
				@"update Employee set LastName = 'newvalue';
					update WorkOrder set Description = 'newvalue';";
			command.ExecuteNonQuery();

			session.SaveOrUpdate(employee);
			session.SaveOrUpdate(order);
			session.Flush();
			session.Dispose();

			var reloadedEmployee = getSession().Load<Employee>(employee.Id);
			var reloadedWorkOrder = getSession().Load<WorkOrder>(order.Id);

			Assert.That(reloadedEmployee.FirstName, Is.EqualTo("newvalue"));
			Assert.That(reloadedEmployee.LastName, Is.EqualTo("newvalue"));
			Assert.That(reloadedWorkOrder.Title, Is.EqualTo("newvalue"));
			Assert.That(reloadedWorkOrder.Description, Is.EqualTo("oldvalue"));
		}

		[Test]
		public void Question2()
		{
			var employee = new Employee("1", "1", "1", "1");
			employee.HomeAddress.StreetAddress = "street";
			employee.HomeAddress.City = "city";
			employee.HomeAddress.State = "TX";
			employee.HomeAddress.ZipCode = "90210";

			var order = new WorkOrder
			            	{
			            		Creator = employee,
			            		Assignee = employee,
			            		CreatedDate = new DateTime(1999, 1, 1),
			            		CompletedDate = new DateTime(1999, 1, 2),
			            		Title = "foo",
			            		Description = "oldvalue",
			            		Status = WorkOrderStatus.InProgress,
			            		Number = "123"
			            	};
			order.Facility.Name = "facility";
			order.Facility.Address.StreetAddress = "street";
			order.Facility.Address.City = "city";
			order.Facility.Address.State = "TX";
			order.Facility.Address.ZipCode = "77777";

			using (ISession session = getSession())
			{
				session.SaveOrUpdate(employee);
				session.SaveOrUpdate(order);
				session.Flush();
			}

			var reloadedEmployee = getSession().Load<Employee>(employee.Id);
			var reloadedWorkOrder = getSession().Load<WorkOrder>(order.Id);

			Assert.That(reloadedEmployee.HomeAddress.StreetAddress, Is.EqualTo("street"));
			Assert.That(reloadedEmployee.HomeAddress.City, Is.EqualTo("city"));
			Assert.That(reloadedEmployee.HomeAddress.State, Is.EqualTo("TX"));
			Assert.That(reloadedEmployee.HomeAddress.ZipCode, Is.EqualTo("90210"));

			Assert.That(reloadedWorkOrder.Facility.Name, Is.EqualTo("facility"));
			Assert.That(reloadedWorkOrder.Facility.Address.StreetAddress,
			            Is.EqualTo("street"));
			Assert.That(reloadedWorkOrder.Facility.Address.City, Is.EqualTo("city"));
			Assert.That(reloadedWorkOrder.Facility.Address.State, Is.EqualTo("TX"));
			Assert.That(reloadedWorkOrder.Facility.Address.ZipCode, Is.EqualTo("77777"));
		}

		[Test]
		public void Question3()
		{
			var employee = new Employee("1", "1", "1", "1");
			var order = new WorkOrder
			            	{
			            		Number = Guid.NewGuid().ToString().Substring(0, 5).ToUpper(),
			            		Creator = employee,
			            		Assignee = employee,
			            		CreatedDate = DateTime.Now,
			            		Status = WorkOrderStatus.Draft,
			            		Title = "Work Order",
			            		Description = "Foo, foo, foo, foo"
			            	};
			order.ChangeStatus(WorkOrderStatus.Draft, employee, DateTime.Now);
			order.ChangeStatus(WorkOrderStatus.Assigned, employee, DateTime.Now);

			using (ISession session = getSession())
			{
				session.SaveOrUpdate(employee);
				session.SaveOrUpdate(order);
				session.Flush();
			}

			ISession loadingSession = getSession();
			IQuery query = loadingSession.CreateQuery(
				@"from WorkOrder w join fetch w.History where w.Id = :id");
			query.SetGuid("id", order.Id);
			var reloadedWorkOrder = query.UniqueResult<WorkOrder>();
			getSession().Dispose(); //discard active session

			Assert.That(reloadedWorkOrder.GetHistory().Length, Is.EqualTo(2));
		}

		[Test]
		public void Question4()
		{
			var employee = new Employee("1", "1", "1", "1");
			var order = new WorkOrder
			            	{
			            		Number = Guid.NewGuid().ToString().Substring(0, 5).ToUpper(),
			            		Creator = employee,
			            		Assignee = employee,
			            		CreatedDate = DateTime.Now,
			            		Status = WorkOrderStatus.Draft,
			            		Title = "Work Order",
			            		Description = "Foo, foo, foo, foo"
			            	};
			order.ChangeStatus(WorkOrderStatus.Draft, employee, DateTime.Now);
			order.ChangeStatus(WorkOrderStatus.Assigned, employee, DateTime.Now);

			using (ISession session = getSession())
			{
				session.SaveOrUpdate(employee);
				session.SaveOrUpdate(order);
				session.Flush();
			}

			var reloadedWorkOrder = getSession().Load<WorkOrder>(order.Id);
			Assert.That(reloadedWorkOrder.HistoryLength, Is.EqualTo(2));
		}
	}
}